import { LinkedList, Node } from "./linked_list";

class DoublyNode extends Node {
  public pre: any;
  constructor(ele: any) {
    super(ele);
    this.pre = null;
  }
}
/**
 * 双向链表封装
 */
class DoublyLikedList extends LinkedList {
  public tail: any;
  constructor() {
    super();
    // 尾节点
    this.tail = null;
  }

  /**
   * 在尾部插入
   * @param ele
   */
  append(ele: any) {
    const newNode = new DoublyNode(ele);
    if (this.head === null) {
      this.head = newNode;
      this.tail = newNode;
    } else {
      // 尾巴的next等于新加进来的node
      this.tail.next = newNode;
      // 新node的前等于之前的尾巴
      newNode.pre = this.tail;
      // 最后将尾巴指向新的节点
      this.tail = newNode;
    }
    this.length++;
  }

  /**
   * 在某个位置插入
   * @param position
   * @param ele
   * @returns
   */
  insert(position: number, ele: any) {
    if (position < 0 || position > this.length) return;

    const newNode = new DoublyNode(ele);
    // 在头部插入
    if (position === 0) {
      this.head.pre = newNode;
      newNode.next = this.head;
      this.head = newNode;
    } else if (position === this.length) {
      this.tail.next = newNode;
      newNode.pre = this.tail;
      this.tail = newNode;
    } else {
      let i = 0;
      let cur = this.head;
      let pre = null;
      while (i++ < position) {
        pre = cur;
        cur = cur.next;
      }
      pre.next = newNode;
      newNode.pre = pre;
      newNode.next = cur;
    }
    this.length++;
  }

  // 移除某个位置的
  removeAt(position: number): any {
    if (position < 0 || position > this.length) return;
    let cur = this.head;
    if (position === 0) {
      this.head = this.head.next;
      // 在将头的指向null
      this.head.pre = null;
      if (this.length === 1) {
        this.tail = null;
      }
    } else if (position === this.length - 1) {
      cur = this.tail;
      // 尾巴的上一个的next就是表示自己 先将自己的next先设置为null
      this.tail.pre.next = null;
      // 这个时候在将尾巴指向当前尾巴的上一个
      // 相当于忽略它 就意味着删除了
      this.tail = this.tail.pre;
    } else {
      let i = 0;

      let pre = null;
      while (i++ < position) {
        pre = cur;
        cur = cur.next;
      }
      pre.next = cur.next;
      // 当前的引用的next的上一层应该为当前的删除的上一个节点
      cur.next.pre = pre;
    }
    this.length--;
    return cur.ele;
  }

  /**
   * 删除某个元素
   * @param ele
   */
  remove(ele: any): any {
    const index = this.indexOf(ele);
    return this.removeAt(index);
  }
}

export { DoublyLikedList };
